package com.base.api.pubg.crawl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.base.api.pubg.enums.PUBG;
import com.base.utils.RedisServer;
import com.base.utils.ResultUtil;
import com.base.utils.enums.RESULT_CODE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

/**
 * 下载数据
 *
 * @author: junw
 * @date: 2018/5/22 10:42
 */
@Component
public class DownloadData {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private DownloadConfig downloadConfig;

    private boolean isWork = false;

    private JSONObject downloaderInfo = new JSONObject();

    public int allSeed = 0;

    @Autowired
    public DownloadData(DownloadConfig downloadConfig) {
        this.downloadConfig = downloadConfig;
    }

    /**
     * 获取下载器是否正在工作
     *
     * @return
     */
    public boolean isWork() {
        return isWork;
    }

    /**
     * 启动下载器
     *
     * @return
     */
    public synchronized String run() {
        try{
            isWork = true;
            download();
            RedisServer redisServer = downloadConfig.getRedisServer();
            logger.error("test_remain=" + redisServer.listSize(PUBG.QUEUE.getDesc()) + redisServer.listSize(PUBG.TEMPQUEUE.getDesc()));
            return ResultUtil.success("下载器启动成功!");
        }catch (Exception e){
            isWork = false;
            logger.info("启动下载器失败！原因：" + e.getMessage());
            return ResultUtil.error(RESULT_CODE.FAIL.getCode(), "下载器启动失败!原因：" + e.getMessage());
        }
    }

    /**
     * 启动线程
     *
     * @throws Exception
     */
    private void download() throws IOException {
        /**
         * 初始化队列
         */
        logger.info("开始初始化。。。");
        checkRedisServer(downloadConfig.getRedisServer());
        downloadConfig.getRedisServer().remove(PUBG.QUEUE.getDesc(), PUBG.TEMPQUEUE.getDesc());

        /**
         * 将所有种子加入队列
         */
        for(String id : getAllMatches(downloadConfig.getNameArray())){
            downloadConfig.getRedisServer().lpush(PUBG.QUEUE.getDesc(), id);
        }

        /**
         * 启动下载线程
         */
        logger.info("启动" + downloadConfig.getThreadCount() + "条线程。");
        final List<Thread> threadList = new ArrayList<>();
        downloadConfig.setThreadList(threadList);
        for (int i = 0; i < downloadConfig.getThreadCount(); i++) {
            Thread thread = new Thread(new DownloadThread(downloadConfig), "Downloader" + i);
            threadList.add(thread);
            thread.start();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                boolean isRun = true;
                /**
                 * 守护下载线程
                 */
                while (isRun) {
                    for (int k = 0; k < threadList.size(); k++) {
                        Thread thread = threadList.get(k);
                        if (!thread.isAlive()) {
                            threadList.remove(thread);
                            if(!downloadConfig.isClose() && downloadConfig.getRedisServer().listSize(PUBG.QUEUE.getDesc()) > 0){
                                thread = new Thread(new DownloadThread(downloadConfig), "Downloader" + k);
                                threadList.add(k, thread);
                                thread.start();
                            }
                        }
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    logger.info("心跳检测...当前线程数：".concat(String.valueOf(downloadConfig.getCurrentThreadCount())).concat("，剩余种子数：")
                            .concat(String.valueOf(downloadConfig.waitingForDownload())));
                    if(threadList.size() < 1){
                        logger.info("下载任务完成！");
                        isWork = false;
                        isRun = false;
                        allSeed = 0;
                    }
                }
            }
        }).start();
    }

    /**
     * 获取一个或多个用户近期比赛ID
     *
     * @param names 一个或多个角色名
     * @return 比赛ID的List集合
     */
    private Set<String> getAllMatches(String... names) throws IOException {
        logger.info("开始装载。。。");
        Set<String> allMatches = new HashSet<>();
        JSONArray data = downloadConfig.getPubgHttpClient().getPlayersInfoByName(names).getJSONArray("data");
        if(data == null || data.size() < 1){
            throw new IOException("查无数据");
        }
        Iterator<Object> dataIterator = data.iterator();
        while (dataIterator.hasNext()){
            JSONObject object = (JSONObject) dataIterator.next();
            JSONArray array = object.getJSONObject("relationships").getJSONObject("matches").getJSONArray("data");
            String name = object.getJSONObject("attributes").getString("name");
            Iterator<Object> arrayIterator = array.iterator();
            while (arrayIterator.hasNext()){
                allMatches.add(((JSONObject) arrayIterator.next()).getString("id").concat(",").concat(name));
            }
        }
        allSeed = allMatches.size();
        logger.info("装载完成！共：" + allMatches.size() + "个！");
        return allMatches;
    }

    /**
     * 检查Redis成功连接
     *
     * @param redisServer
     */
    private void checkRedisServer(RedisServer redisServer) {
        try{
            redisServer.exist("");
        }catch (RedisConnectionFailureException e){
            logger.info("Redis连接失败！原因：" + e.getMessage());
            throw e;
        }
        logger.info("Redis连接成功！");
    }

    public DownloadConfig getDownloadConfig() {
        return downloadConfig;
    }

    public JSONObject getDownloaderInfo() {
        return downloaderInfo;
    }
}
